""" Tests for Tavr compiler """

from S3D.Tavr.TavrCompiler import TavrCompiler
from unittest import TestCase

class TavrTests(TestCase):
    def setUp(self):
        self.c = TavrCompiler()

    def tearDown(self):
        self.c = None

    def checkDef(self, sourceDefs, testDefs):
        self.assertEqual(len(sourceDefs), len(testDefs))

        d = testDefs
        for k in range(len(d)):
            a_d = sourceDefs[k]
            self.assertEqual(a_d.name, d[k][0])

            for kkk in range(len(d[k][1])):
                arg = d[k][1][kkk]
                if isinstance(arg, tuple):
                    self.assertEqual(a_d.args[kkk].name, arg[0])
                    self.assertEqual(str(a_d.args[kkk].defVal), arg[1])
                else:
                    self.assertEqual(a_d.args[kkk].name, arg)
                    self.assertEqual(a_d.args[kkk].defVal, None)

    def compile(self, text, imports = [], autos = [], vars = None, defs = None, globalDefs = None):
        r = self.c.compile(text)

        self.assertFalse(r is None, msg = self.c.errorMsg)
        self.assertEqual(self.c.errorMsg,   "")
        self.assertEqual(self.c.errorsCount, 0)

        self.assertEqual(len(r.imports),    len(imports))
        for index in range(len(imports)):
            self.assertEqual(str(r.imports[index]), imports[index])

        self.assertEqual(len(r.autos),      len(autos))
        for index in range(len(autos)):
            if isinstance(autos[index], tuple):
                self.assertEqual(r.autos[index].name, autos[index][0])
                self.assertEqual(str(r.autos[index].parent), autos[index][1])
            else:
                self.assertEqual(r.autos[index].name, autos[index])

        if vars is None:
            for a in r.autos:
                self.assertEqual(len(a.vars), 0)
        else:
            self.assertEqual(len(autos), len(vars))
            for index in range(len(vars)):
                a = r.autos[index]
                v = vars[index]
                self.assertEqual(len(a.vars), len(v))

                for k in range(len(v)):
                    if isinstance(v[k], tuple):
                        self.assertEqual(a.vars[k].name, v[k][0])
                        self.assertEqual(str(a.vars[k].defVal), v[k][1])
                    else:
                        self.assertEqual(a.vars[k].name, v[k])
                        self.assertEqual(a.vars[k].defVal, None)

        if defs is None:
            for a in r.autos:
                self.assertEqual(len(a.defs), 0)
        else:
            self.assertEqual(len(autos), len(defs))
            for index in range(len(defs)):
                a = r.autos[index]
                d = defs[index]

                self.checkDef(a.defs, d)

        if globalDefs is None:
            self.assertEqual(len(r.defs), 0)
        else:
            self.checkDef(r.defs, globalDefs)

        return r

    def test_imports(self):
        self.compile("""
            import a.b.c.*;
            import someOtherImport;
            import testAll.*;
        """, imports = ["a.b.c.*", "someOtherImport", "testAll.*"])

    def test_auto(self):
        self.compile("""
            auto MyAuto {}
            auto Child : Namespace.MyAuto {}
        """, autos = ["MyAuto", ("Child", "Namespace.MyAuto")])

    def test_vars(self):
        self.compile("""
            auto MyVars {
                var a0, c1;
                var varWithDefVal = 10.1, stringVar = "Hello world!";
                var wordVar = aWord;
            }
        """, autos = ["MyVars"], vars = [
            ['a0', 'c1',
                ('varWithDefVal', '10.1'),
                ("stringVar", '"Hello world!"'),
                ('wordVar', 'aWord')]
        ])

    def test_defs(self):
        self.compile("""
            auto AutoWithDefsAndVars : SomeParent {
                var myVar = 100500;

                def test() {}
                def test(a, b, c) {}
                def test123(a, b = 10, c = "hello world") {}
            }
        """,
            autos = [('AutoWithDefsAndVars', 'SomeParent')],
            vars  = [[('myVar', "100500")]],
            defs  = [[
                             ('test', []),
                             ('test', ['a', 'b', 'c']),
                             ('test123', ['a', ('b', '10'), ('c', '"hello world"')])
                     ]])

    def test_globalDefs(self):
        self.compile("""
            def globalDef(a, b, c) {}
            def testGloabs(a = 10, b = 10.0, c = word, d = "string") {}
            def testEmpty() {}
        """,
            globalDefs = [
                ('globalDef', ['a', 'b', 'c']),
                ('testGloabs', [('a', '10'), ('b', '10.0'), ('c', 'word'), ('d', '"string"')]),
                ('testEmpty', [])
            ])

    def test_statements(self):
        self.compile("""
            def test(someArg) {
                //left = left2 = someArg * 2;
                //a = b * c + d;
                //eee = (1 + 2) * d - 123;
                //unar = +---+123;
                //uner = 10 * -d;
                //return someArg + 1;
            }
        """,
            globalDefs = [
                ('test', ['someArg'])
            ])